The present invention relates to the communication between routines on a computer system, and in particular, to the communication between one routine written in a first computer language and another routine written in a second computer language.
Programs written in a first computer language sometimes call procedures written in a second computer language. A call from a program written in a first computer language to a routine written in a second computer language is referred to as an external callout. The program written in the second computer language is referred to as an external routine. Typically, the first and second computer languages support equivalent data types.
External callouts from routines written in a first computer language to routines written in a second computer language are more problematic when the second computer language does not support data types equivalent to one or more data types of the first computer language. For example, in PL/SQL(trademark), a procedural database language available from Oracle corporation, a BINARY_INTEGER variable can specify any integer value but can also be null. Thus, each such variable is represented by a data structure that shares an integer value and a null flag. The corresponding C integer types (e.g. long, short) cannot represent a null value, and therefore do not have a null flag. Similarly, a PL/SQL(trademark) variable of type VARCHAR2 has an associated LENGTH and MAXIMUM LENGTH, whereas the corresponding C string data type does not.
If it were desired to provide an external call to a C procedure from a PL/SQL routine, in order to communicate attribute information associated with PL/SQL(trademark) variables to the C procedure, the parameter list of the C procedure could be designed with one or more additional (xe2x80x9cattributexe2x80x9d) parameters for storing the attribute information. These attribute parameters would have to be appropriately set before each call to the C procedure and examined upon return from the C procedure call. For example, consider an external C routine that performs an operation based upon input data represented by a PL/SQL(trademark) variable of the BINARY_INTEGER data type, and that can modify the received value (including setting to null), and that has the following prototype:
foo (x long, x_null_flag short)
where x is a xe2x80x9clongxe2x80x9d integer value in C and x_null_flag is a xe2x80x9cshortxe2x80x9d integer value in C that serves as a flag to indicate whether the input value x is supposed to be null. No input value supplied for x can be used to indicate null because all possible values of x represent valid integers.
Each call to foo from the PL/SQL program must do the following:
1. pass in a value for the x_null_flag parameter to indicate to the C procedure whether or not the PL/SQL integer variable passed in for the x parameter is null (e.g. x_null_flag=1 indicates null, x_null_flag=0 indicates not null);
2. upon return from the call, checking the value returned for the x_null_flag parameter, and if the value is xe2x88x921, setting the PL/SQL integer variable passed in for the x parameter to null.
One possible approach for passing the required attribute information between a PL/SQL program and C routine is the xe2x80x9chard-codedxe2x80x9d approach. In the hard-coded approach, the PL/SQL programmer provides code that explicitly sets the appropriate attribute parameters before each call to an external procedure, and examines the attribute parameters after each call.
The hard-coded approach is tedious and error-prone. For example, before each call to the procedure foo defined above, the PL/SQL programmer provides the code needed to perform some testing and setting of parameter variables. The following (where X1 and X2 are PL/SQL integers passed in as first and second parameters on the call to foo):
IF (X1 IS NULL) THEN
X2=xe2x88x921
ELSE
X2=0;
END IF;
In addition, upon return from each call to the procedure foo the PL/SQL programmer needs to perform some testing like the following:
IF (X2=xe2x88x921) THEN
X1:=NULL;
END IF;
Even if the problems of programmer tedium and error were tolerable, the above hard-coded approach might not provide a general solution, given that some types of attribute information might not be accessible to the PL/SQL(trademark) programmer. For example, there is currently no means for the PL/SQL(trademark) programmer to determine the MAXLEN associated with a PL/SQL(trademark) variable. For these types of attributes, it is not possible for the programmer to determine what attribute values to send to the external routine.
Finally, given that PL/SQL(trademark) is an interpretive language, the hard-coded approach involves increasing the amount of code that must be interpreted at runtime, which in turn, adversely impacts performance.
Based on the foregoing, it is clearly desirable to provide a method which reduces the tedium and error-proneness associated with programmer supplied code that explicitly sets and tests attribute parameter values before and after, respectively, each external callout. It is further desirable to provide a method of communicating to an external routine attribute information not available to the programmer. Finally, it is desirable to provide a method that reduces the adverse impact upon performance associated with the hard-coded approach and resulting from an increased amount of code to be interpreted at runtime.
A method and apparatus for communicating between a called routine written in a first programming language and calling routine written in a second programming language is provided. According to one aspect of the invention, user input is received. The user input specifies an interface of a proxy routine and the interface parameters of the interface. Metadata that is generated establishes a mapping of interface parameters to the routine parameters of the called routine. At least one interface parameter is of a data type not supported in the first programming language.
According to another aspect of the invention, the user input specifies that a first attribute of a particular interface parameter is mapped to a first routine parameter of the called routine, and a second attribute of the particular interface parameter is mapped to a second routine parameter of the called routine. The metadata maps the first attribute to the first routine parameter, and the second attribute to the second routine parameter. When the user input specifies no mapping of the interface parameters to the routine parameters of the called routine, the metadata establishes a mapping according to a default set of rules.
According to another aspect of the invention, in response to invoking the proxy routine, a first set of values is passed for the interface parameters. The metadata is read to determine the mapping between the interface parameters and the routine parameters of the called routine, and then a second set of values is passed to the called routine for the routine parameters of the called routine.
According to another aspect of the invention, the metadata contains foreign argument descriptors that are mapped to an attribute of a particular interface parameter and to a routine parameter of the called routine. If a routine parameter is associated with a base attribute of a particular interface parameter, then a value, based on the base attribute, is passed to the called routine for the routine parameter associated with the foreign argument descriptor. The foreign argument descriptor may be linked to another routine parameter descriptor, which is associated with another attribute of the particular interface parameter. If the foreign argument descriptor is linked to another foreign argument descriptor, then a value, based on an attribute other than the base attribute, is passed to the called routine for the routine parameter mapped to the other foreign argument descriptor.